using Crux.Core.Data;

namespace Crux.Core.NHibernate;
/// <summary>
/// IUnitOfWork
/// </summary>
public interface IUnitOfWork<out TContext>
    : IDisposableObservable, IAsyncDisposableObservable
    where TContext : NHibernateContext
{
    /// <summary>
    ///
    /// </summary>
    TContext Context { get; }
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="entity"></param>
    TEntity Add<TEntity>(TEntity entity) where TEntity : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="entity"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<TEntity> AddAsync<TEntity>(
        TEntity entity,
        CancellationToken cancellationToken = default) where TEntity : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="entities"></param>
    IEnumerable<TEntity> Add<TEntity>(IEnumerable<TEntity> entities) where TEntity : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="entities"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<IEnumerable<TEntity>> AddAsync<TEntity>(
        IEnumerable<TEntity> entities,
        CancellationToken cancellationToken = default) where TEntity : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entity"></param>
    /// <returns></returns>
    T Update<T>(T entity) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entities"></param>
    /// <returns></returns>
    IEnumerable<T> UpdateRange<T>(IEnumerable<T> entities) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="where"></param>
    /// <param name="updateExpression"></param>
    /// <returns></returns>
    int Update<T>(
        Expression<Func<T, bool>> where,
        Expression<Func<T, T>> updateExpression) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entity"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<T> UpdateAsync<T>(
         T entity,
        CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entities"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<IEnumerable<T>> UpdateRangeAsync<T>(
         IEnumerable<T> entities,
        CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="where"></param>
    /// <param name="updateExpression"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<int> UpdateAsync<T>(
        Expression<Func<T, bool>> where,
        Expression<Func<T, T>> updateExpression,
        CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entity"></param>
    /// <returns></returns>
    T Delete<T>(T entity) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entities"></param>
    /// <returns></returns>
    IEnumerable<T> DeleteRange<T>(IEnumerable<T> entities) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="where"></param>
    /// <returns></returns>
    int Delete<T>(Expression<Func<T, bool>> where) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entity"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<T> DeleteAsync<T>(
         T entity,
        CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entities"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<IEnumerable<T>> DeleteRangeAsync<T>(
         IEnumerable<T> entities,
        CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="where"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<int> DeleteAsync<T>(
        Expression<Func<T, bool>> where,
        CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="where"></param>
    /// <returns></returns>
    int SoftDelete<T>(Expression<Func<T, bool>> where) where T : class, ISoftDelete;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="where"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<int> SoftDeleteAsync<T>(Expression<Func<T, bool>> where, CancellationToken cancellationToken = default) where T : class, ISoftDelete;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="where"></param>
    /// <returns></returns>
    int PhysicsDelete<T>(Expression<Func<T, bool>> where) where T : class, ISoftDelete;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="where"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<int> PhysicsDeleteAsync<T>(Expression<Func<T, bool>> where, CancellationToken cancellationToken = default) where T : class, ISoftDelete;
}
